package com.hongmeng.teamwork.utils;

import com.hongmeng.teamwork.constants.JwtConstant;
import io.jsonwebtoken.*;

import java.util.Date;
import java.util.Map;
import java.util.Optional;

/**
 * Jwt 工具类
 */
public class JwtUtil {

    /**
     * 创建 token
     */
    public static String createToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims) // 把荷载存储到里面
                .setExpiration(generateExpirationDate()) // 设置失效时间
                .signWith(SignatureAlgorithm.ES512, JwtConstant.JWT_SECRET)
                .compact();
    }

    /**
     * 从令牌中取出数据声明
     */
    public static Claims parseToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(JwtConstant.JWT_SECRET)
                    .parseClaimsJwt(token)
                    .getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return claims;
    }

    /**
     * 生成失效时间
     */
    private static Date generateExpirationDate() {
        // 失效时间是当前系统时间 + 我们配置时间
        return new Date(System.currentTimeMillis() + JwtConstant.JWT_EXPIRATION);
    }

    /**
     * 验证 token 是否有效
     */
    public static boolean validateToken(String token) {
        // claims 为 null 意味着 jwt 被修改
        Claims claims = parseToken(token);
        return claims != null && !isTokenExpired(token);
    }

    private static boolean isTokenExpired(String token) {
        // 先获取之前设置的 token 失效时间
        Date expireDate = getExpireDate(token);
        return expireDate.before(new Date()); // 判断当前时间是否已经在 expireDate 之后
    }

    /**
     * 根据 token 获取失效时间
     * 也是先从 token 中获取 荷载
     * 然后从荷载中拿到设置的失效时间
     */
    private static Date getExpireDate(String token) {
        Claims claims = parseToken(token);
        return claims.getExpiration();
    }

    /**
     * 刷新 token
     */
    public static String refreshToken(String token) {
        Claims claims = parseToken(token);
        claims.put(JwtConstant.JWT_CREATE_TIME, new Date());
        return createToken(claims);
    }

    /**
     * 根据身份信息获取键值
     */
    public static String getValue(Claims claims, String key) {
        return (String) Optional.ofNullable(claims.get(key)).get();
    }

    public static String getAccessToken(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, JwtConstant.ACCESS_TOKEN);
    }

    public static String getOpenId(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, JwtConstant.OPEN_ID);
    }

    public static String getUserJson(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, JwtConstant.USER_JSON);
    }
}
